using System.Threading.Tasks;
using Identity.Application.Contracts.Common;
using Identity.Application.Permissions.Interfaces;
using Identity.Domain.Aggregates;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;

namespace Identity.Infrastructure.Persistence.ReadServices;

public class PermissionReadService : IPermissionsReadService
{
    private readonly ApplicationDbContext _context;

    public PermissionReadService(ApplicationDbContext context)
    {
        _context = context;
    }


    public async Task<IEnumerable<PermissionDto>> GetListAsync(string? keyword = null, CancellationToken cancellationToken = default)
    {
        var query = _context.Permissions.AsNoTracking().AsQueryable();

        if (!string.IsNullOrEmpty(keyword))
        {
            query = query.Where(b => b.Name.Contains(keyword));
        }
        return from a in query
               join b in _context.ApiPermissionBindings
               on a.Id equals b.permissionId into ab
               from b in ab.DefaultIfEmpty()
               select new PermissionDto(a.Id, a.Name, a.Key, a.Description, b != null ? b.FromServiceName : null, b != null);
               
        
    }

    public async Task<PermissionDto?> GetByIdAsync(Guid id)
    {
        var query = _context.Permissions.AsNoTracking();

        var per = await query.Where(p => p.Id == id).FirstOrDefaultAsync();

        if (per == null) return null;
        return await GetPermissionDto(per);
    }

    public async Task<PermissionDto?> GetByKeyAsync(string PermissionKey)
    {
        var query = _context.Permissions.AsNoTracking().AsQueryable();

        var per = await query.Where(p => p.Key == PermissionKey).FirstOrDefaultAsync();

        if (per == null) return null;

        return await GetPermissionDto(per);
    }

    public async Task<List<PermissionDto>> GetUnboundPermissionsForApiAsync()
    {
        var query = _context.Permissions.AsNoTracking().AsQueryable();
        var bingdIds = _context.ApiPermissionBindings.Select(b => b.permissionId).ToHashSet();
        var unboundPers = query.Where(p => !bingdIds.Contains(p.Id)).Select(per => new PermissionDto(per.Id, per.Name, per.Key, per.Description,null, false));
        return await unboundPers.ToListAsync();

    }

    public async Task<List<PermissionAndApiServiceNameDto>> GetBoundPermissionsForApiAsync()
    {
        var boundPers =
            from q in _context.Permissions.AsNoTracking()
            join b in _context.ApiPermissionBindings
                on q.Id equals b.permissionId into qb
            from b in qb.DefaultIfEmpty()
            select new PermissionAndApiServiceNameDto(
                q.Id,
                q.Name,
                q.Key,
                q.Description,
                b != null ? b.FromServiceName : null,   // serviceName 可能为空
                b != null                               // 是否绑定
            );


        return await boundPers.ToListAsync();
    }


    private async Task<PermissionDto?> GetPermissionDto(Permission permission)
    {

        var BindingApiPermissionId = await _context.ApiPermissionBindings.Where(p => p.permissionId == permission.Id).Select(per => new { id = per.permissionId, serviceName = per.FromServiceName }).FirstOrDefaultAsync();
        

        var permissiondto = new PermissionDto(permission.Id, permission.Name, permission.Key, permission.Description, BindingApiPermissionId?.serviceName, BindingApiPermissionId!=null);
        return permissiondto;
    }
}